package com.zxy.bilibili;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zxy.bilibili.entity.BiCacheFile;
import com.zxy.bilibili.util.FfmpegUtils;
import com.zxy.bilibili.util.FileUtils;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * ConvertHelper
 *
 * @author ZENG.XIAO.YAN
 * @version 1.0
 * @Date 2020-11-02
 */
@Slf4j
public class ConvertHelper {

    /**
     * description: 转换核心方法
     * @param sourceFileDirPath  视频源文件路径
     * @param targetFileDirPath  视频输出路径
     * @return void
     * @author ZENG.XIAO.YAN
     * @time 2020-11-02 11:45
     */
    public static void doConvert(String sourceFileDirPath, String targetFileDirPath) {
        // 1.获取所有文件
        File sourceFileDir = new File(sourceFileDirPath);
        List<File> fileList = FileUtils.listAllFile(sourceFileDir);
        // 2.文件分组
        List<File> entryJsonList = fileList.stream().filter(x -> x.getName().equals("entry.json")).collect(Collectors.toList());
        List<File> audioFileList = fileList.stream().filter(x -> x.getName().equals("audio.m4s")).collect(Collectors.toList());
        List<File> videoFileList = fileList.stream().filter(x -> x.getName().equals("video.m4s")).collect(Collectors.toList());
        // 3.文件信息构造
        List<BiCacheFile> biCacheFileList = new ArrayList<>();
        // 3.1 先解析json文件
        entryJsonList.stream().forEach(x -> {
            // 获取某个p对应的文件夹名字
            String partFileDirName = x.getParentFile().getName();
            BiCacheFile biCacheFile = parseEntryJsonFile(x);
            if (biCacheFile != null) {
                biCacheFile.setPartFileDirName(partFileDirName);
                biCacheFileList.add(biCacheFile);
            }
        });
        // 3.2 音频文件 通过文件夹路径和上面解析后的BiCacheFile进行配对并复制
        audioFileList.stream().forEach(x -> {
            String partDirName = x.getParentFile().getParentFile().getName();
            String avIdStr = x.getParentFile().getParentFile().getParentFile().getName();
            biCacheFileList.stream()
                    .filter(y -> partDirName.equals(y.getPartFileDirName()) && avIdStr.equals(y.getAvId().toString()))
                    .findAny().ifPresent(z -> z.setAudioFilePath(x.getPath()));
        });
        // 3.3 视频文件 通过文件夹路径和上面解析后的BiCacheFile进行配对并复制
        videoFileList.stream().forEach(x -> {
            String partDirName = x.getParentFile().getParentFile().getName();
            String avIdStr = x.getParentFile().getParentFile().getParentFile().getName();
            biCacheFileList.stream()
                    .filter(y -> partDirName.equals(y.getPartFileDirName()) && avIdStr.equals(y.getAvId().toString()))
                    .findAny().ifPresent(z -> z.setVideoFilePath(x.getPath()));
        });
        // 4.开始转换
        biCacheFileList.stream().parallel().forEach(x -> {
            // log.info("{},开始转换", x.getPartFileName());
            // av标题用来做大文件夹
            String avTitle = x.getAvTitle();
            File outFile = new File(targetFileDirPath, avTitle + File.separator + x.getPartFileName() + ".mp4");
            if (!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdirs();
            }
            if (outFile.exists()) {
                log.info("{},已存在无需转换", x.getPartFileName());
            } else {
                FfmpegUtils.doMpeg(x.getAudioFilePath(), x.getVideoFilePath(), outFile.getPath());
                log.info("{},转换成功", x.getPartFileName());
            }
        });
    }


    /**
     * description: 解析entry.json文件
     * @param jsonFile
     * @return com.zxy.bilibili.entity.BiCacheFile
     * @author ZENG.XIAO.YAN
     * @time 2020-08-08 14:13
     */
    private static BiCacheFile parseEntryJsonFile(File jsonFile) {
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(jsonFile)))) {
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                sb.append(line);
            }
            String jsonStr = sb.toString();
            Map map = JSON.parseObject(jsonStr, Map.class);
            if (map.containsKey("title") && map.containsKey("avid")) {
                BiCacheFile biCacheFile = new BiCacheFile();
                biCacheFile.setAvId((Integer) map.get("avid"));
                biCacheFile.setAvTitle((String) map.get("title"));
                if (map.containsKey("page_data")) {
                    JSONObject pagData = (JSONObject) map.get("page_data");
                    biCacheFile.setPartFileName((String) pagData.get("part"));
                }
                return biCacheFile;
            }
        } catch (Exception e) {
            log.error("json解析异常", e);
        }
        return null;
    }
}
